# 此类专门用于搜狗邮箱发邮件，因搜狗邮箱没有开通smtp服务器，所以只能采用exchange服务器发送邮件
from exchangelib import DELEGATE, Account, Credentials, Configuration, NTLM, Message, Mailbox, HTMLBody, FileAttachment, Body
import sys
from os.path import dirname, abspath

# from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter
# 此句用来消除ssl证书错误，exchange使用自签证书需加上
# HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter


class ExchangeUtil:

    def __init__(self, subject, receiver_list, cc_receiver_list=[], bcc_receiver_list=[], sender='itfin_bigdata_common@sogou-inc.com', password=''):
        self.sender = sender
        self.password = password
        self.server = 'mail.sogou-inc.com'
        # 校验账号和密码
        cred = Credentials(self.sender, self.password)
        print("账户验证成功")
        # 账户的配置文件
        config = Configuration(server=self.server, credentials=cred, auth_type=NTLM)
        print("配置文件设置成功")
        # 生成账户
        self.account = Account(primary_smtp_address=sender, config=config, autodiscover=False, access_type=DELEGATE)
        print("发邮件主体账户创建成功")
        # 创建发邮件主题
        self.msg_root = Message(account=self.account,
                                folder=self.account.sent,
                                subject=subject,
                                to_recipients=receiver_list,
                                cc_recipients=cc_receiver_list,
                                bcc_recipients=bcc_receiver_list)
        print("邮件root类初始化成功")

    # 添加正文内容
    def set_content(self, content, content_type='plain'):
        if content_type == 'plain':
            self.msg_root.body = Body(content)
        elif content_type == 'html':
            self.msg_root.body = HTMLBody(content)
        print("邮件正文添加成功")

    # 添加附件
    def add_file(self, file_name):
        unabs_file_name = file_name.replace('\\', '/').split('/')[-1]
        with open(file_name, 'rb') as f:
            att = FileAttachment(name=unabs_file_name, content=f.read())
        self.msg_root.attach(att)

    # 发送并储存邮件
    def send(self):
        self.msg_root.send_and_save()

    # 重置邮件主体，主要用于多次发送邮件
    def reset_msgroot(self, subject, receiver_list, cc_receiver_list, bcc_receiver_list):
        self.msg_root = Message(account=self.account,
                                folder=self.account.sent,
                                subject=subject,
                                to_recipients=receiver_list,
                                cc_recipients=cc_receiver_list,
                                bcc_recipients=bcc_receiver_list)


# 过滤掉不含@的邮箱地址
def filter_mail_list(list_1):
    return list(filter(lambda x: '@' in x, map(lambda x: x.strip(), list_1)))


# 解析配置文件
def parse_config(config_path):
    tem_dic = {}
    f = open(config_path, 'r')
    i = 0
    for line in f:
        i += 1
        if line.startswith('#'):
            continue
        if line.count('=') != 1 and line.replace(' ', '').replace('\n', '') != '':
            raise Exception("配置文件第%s行出现错误，请检查" % i)
        if '=' in line:
            line_list = list(map(lambda x: x.strip(), line.replace('\n', '').split('=')))
            if line_list[0] in tem_dic:
                raise Exception("对%s参数进行重复配置，请仔细检查，确保参数唯一性" % line_list[0])
            tem_dic[line_list[0]] = line_list[1]
    f.close()

    # 判定主题和正文存在
    lose_keys = {'subject', 'content', 'receiver_list', 'cc_receiver_list', 'bcc_receiver_list'} - tem_dic.keys()
    if len(lose_keys) > 0:
        raise Exception("配置文件缺少以下配置信息：%s，请仔细检查配置文件" % ', '.join(list(lose_keys)))
    assert (tem_dic['subject'] != '')

    # 进一步更新配置文件
    tem_dic['receiver_list'] = filter_mail_list(tem_dic['receiver_list'].split(','))
    tem_dic['cc_receiver_list'] = filter_mail_list(tem_dic['cc_receiver_list'].split(','))
    tem_dic['bcc_receiver_list'] = filter_mail_list(tem_dic['bcc_receiver_list'].split(','))
    tem_dic['file_list'] = list(filter(lambda x: len(x) != 0, map(lambda x: x.strip(), tem_dic['file_list'].split(','))))
    # 判定收件人存在
    assert (len(tem_dic['receiver_list'] + tem_dic['cc_receiver_list'] + tem_dic['bcc_receiver_list']) > 0)

    return tem_dic


if __name__ == '__main__':
    if len(sys.argv) == 1:
        config_path = dirname(abspath(__file__)) + '/send_mail.conf'
        raise Exception("请传入配置文件路径作为参数，配置文件可参照：%s" % config_path)
    else:
        config_path = sys.argv[1]
    parse_result = parse_config(config_path)

    # 获取配置信息
    subject = parse_result['subject']
    content = parse_result['content']
    receiver_list = parse_result['receiver_list']
    cc_receiver_list = parse_result['cc_receiver_list']
    bcc_receiver_list = parse_result['bcc_receiver_list']
    file_list = parse_result['file_list']

    # 设置邮件主体
    mail = ExchangeUtil(subject, receiver_list, cc_receiver_list, bcc_receiver_list)
    # 设置正文
    mail.set_content(content)
    # 添加附件
    for file_name in file_list:
        mail.add_file(file_name)
    mail.send()
